﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Sisocana.Core;
using Sisocana.Core.Models;
using Sisocana.Core.Interfaces;
using Sisocana.Dal.EntityModels;
using Sisocana.Dal;
using Sisocana.Dal.Interfaces;
using System.Data;

namespace Sisocana.Core
{
    public class UsuarioService : ServiceBase<IUsuarioModel>, IUsuarioService
    {
        #region Variables
        private IUsuarioRepository userRepo;
        private ISiteRepository siteRepo;
        #endregion
        #region Constructors
        public UsuarioService()
            : this(new UsuarioRepository(), new SiteRepository())
        {
        }
        public UsuarioService(IUsuarioRepository usuarioRepository, ISiteRepository siteRepository)
        {
            userRepo = usuarioRepository ?? new UsuarioRepository();
            siteRepo = siteRepository ?? new SiteRepository();
        }
        #endregion
        #region Mappers
        public void createUsuarioMapperEF2Model()
        {
            AutoMapper.Mapper.CreateMap<Usuario, UsuarioModel>();
        }
        public void createUsuarioMapperModel2EF() 
        {
            AutoMapper.Mapper.CreateMap<UsuarioModel, Usuario>();
        }
        #endregion

        public UsuarioModel GetSingle(Expression<Func<UsuarioModel, bool>> whereCondition)
        {
            createUsuarioMapperEF2Model();

            IList<Usuario> usuariosEF = userRepo.GetAll();
            List<UsuarioModel> usuarios = new List<UsuarioModel>();

            usuarios = AutoMapper.Mapper.Map(usuariosEF, usuarios);

            IQueryable<UsuarioModel> usuarioRet = usuarios.AsQueryable<UsuarioModel>().Where(whereCondition);

            List<UsuarioModel> ret = usuarioRet.ToList();

            if (ret.Count == 0)
                return null;

            return ret.First();
        }

        public void Add(UsuarioModel entity)
        {
            createUsuarioMapperModel2EF();

            Usuario usu = new Usuario(); 
            usu = AutoMapper.Mapper.Map(entity,usu);

            userRepo.Add(usu);

            userRepo.Save();
        }

        public void Update(UsuarioModel entity)
        {
            createUsuarioMapperModel2EF();

            Usuario usu = userRepo.GetSingle(u => u.nombreUsuario.Trim() == entity.nombreUsuario.Trim());
            AutoMapper.Mapper.Map(entity, usu);

            userRepo.Save();
        }

        public int deleteUser(UsuarioModel entity)
        {
            createUsuarioMapperModel2EF();

            Usuario usu = userRepo.GetSingle(u => u.nombreUsuario.Trim() == entity.nombreUsuario.Trim());
            if (usu == null)
                return -1;
            AutoMapper.Mapper.Map(entity, usu);

            userRepo.Delete(usu);
            try
            {
                userRepo.Save();
                return 0;
            }
            catch (Exception e)
            {
                return e.InnerException.GetHashCode();
            }

        }

        public IList<UsuarioModel> GetAll(Expression<Func<UsuarioModel, bool>> whereCondition)
        {
            createUsuarioMapperEF2Model();

            IList<Usuario> usuariosEF = userRepo.GetAll();
            List<UsuarioModel> usuarios = new List<UsuarioModel>();
            usuarios = AutoMapper.Mapper.Map(usuariosEF, usuarios);
            IQueryable<UsuarioModel> usuarioRet = usuarios.AsQueryable<UsuarioModel>().Where(whereCondition);
            return usuarioRet.ToList();
        }

        public IList<UsuarioModel> GetAll()
        {
            createUsuarioMapperEF2Model();

            IList<Usuario> usuariosEF = userRepo.GetAll();
            List<UsuarioModel> usuarios = new List<UsuarioModel>();

            usuarios = AutoMapper.Mapper.Map(usuariosEF, usuarios);

            return usuarios;
        }

        /// <summary>
        /// Devuelve todos los administradores, más la información de si administran el sitio de id <code>siteId</code>.
        /// </summary>
        /// <param name="siteId"></param>
        /// <returns></returns>
        public IList<UsuarioModel> GetSiteAdmins(int siteId)
        {
            AutoMapper.Mapper.CreateMap<Usuario, UsuarioModel>();
            IList<Usuario> usuariosEF = userRepo.GetAll(u => u.tipo.Equals("S"));
            List<UsuarioModel> usuarios = new List<UsuarioModel>();
            foreach (var usuario in usuariosEF)
            {
                UsuarioModel user = new UsuarioModel();
                user = AutoMapper.Mapper.Map(usuario, user);
                user.check = usuario.Sitio.Any(s => s.id == siteId);
                usuarios.Add(user);
            }
            return usuarios;
        }

        public bool IsAdminGeneral(string adminName)
        {
            return userRepo.GetSingle(u => u.nombreUsuario == adminName).tipo == "G";
        }

        

        #region Not implemented methods
        IQueryable<UsuarioModel> IService<UsuarioModel>.Query(Expression<Func<UsuarioModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        public void Delete(UsuarioModel entity)
        {
            throw new NotImplementedException();
        }

        long IService<UsuarioModel>.Count(Expression<Func<UsuarioModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        long IService<UsuarioModel>.Count()
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
